﻿using System;
using System.Web.Mvc;
using System.Web.Routing;
using ImaginaryDevelopmentMvc3.App.Auth;
using ImaginaryDevelopmentMvc3.Models;
using System.Diagnostics;

namespace ImaginaryDevelopmentMvc3.Controllers
{
    [App.AllowAnonymous]
    public class AuthController : Controller
    {

        public IFormsAuthenticationService _formsService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (_formsService == null) { _formsService = new FormsAuthenticationService(); }

            base.Initialize(requestContext);
        }

        [ValidateInput(false)]
        public ActionResult OpenId()
        {
            return HandleOpenId(Request.Form["openid_identifier"]);
        }

        public ActionResult Facebook()
        {
            var callback = new Uri(new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"))), "/Auth/Callback?type=fb");

            new Facebook().Authenticate(callback);

            return new EmptyResult();
        }

        public ActionResult Google()
        {
            return HandleOpenId("https://www.google.com/accounts/o8/id");

        }

        public ActionResult Yahoo()
        {
            return HandleOpenId("http://yahoo.com/");


        }
        
        public ActionResult WindowsLive()
        {
            var address =App.Auth. WindowsLive.GetCallbackUri(HttpContext);
            var uri = new Uri(address);
            if (uri == null)
                return ErrorOut("callback address failed to generate");
            new WindowsLive().Authenticate(new Uri(address));

            return new EmptyResult();
        }
        public ActionResult Twitter()
        {
            var callback = new Uri(new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"))), "/Auth/Callback?type=tw");

            new Twitter().Authenticate(callback);

            return new EmptyResult();
        }

        public ActionResult Callback(string type)
        {
            IOauthClient client;

            switch (type)
            {
                case "wl": 
                    client = new WindowsLive();
                    break;
                case "tw":
                    client = new Twitter();
                    break;
                case "fb":
                    client = new Facebook();
                    break;
                default:
                    return ErrorOut("No valid Oauth orchestration was found for current callback.");

            }
            
            try
            {
                var userInfo = client.Verify();
                
                   
                TempData["verify"] = "verified";
                return CompleteSignIn(userInfo);
            }
            catch (Exception ex)
            {
                if(type=="wl")
                {
                    var wl=client as WindowsLive;
                    TempData["verifyUrl"] = wl.VerifyUrl;
                    if(wl.WindowsLiveUser!=null) TempData["graph"] =wl.WindowsLiveUser.ToJson();
                    
                }
                TempData["token"] = client.Token;
                return ErrorOut("Verify failed", ex);
            }
            

            
        }

        private ActionResult ErrorOut(string message,Exception ex=null)
        {
            Trace.WriteLine("AuthError:" + message);
#if DEBUG
            if (ex != null)
            {
                TempData["ex"] = ex.ToString();
                TempData["iex"] = ex.InnerException != null ? ex.InnerException.ToString() : "none";
            }

#endif
            TempData["auth_error"] = message;
            return RedirectToAction("LogOn", "Account");
        }
        
        private ActionResult Redirect()
        {
            var cookie = Request.Cookies["returnUrl"];

            if (cookie != null)
            {
                return Redirect(cookie.Value);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        private ActionResult HandleOpenId(string oid)
        {
            try
            {
                var identity = new OpenId().ProcessOpenId(oid);
                if (identity == null) return new EmptyResult();

                return CompleteSignIn(identity);
            }
            catch (Exception ex)
            {
                return ErrorOut(ex.Message,ex);
            }
        }
        private ActionResult CompleteSignIn(OpenIdentity identity)
        {
            if (identity == null)
                return ErrorOut("UserInfo is null");
            if ( string.IsNullOrEmpty(identity.Username))
            {
                return ErrorOut("Invalid Identifier");
            }

            _formsService.SignIn(identity.Username, true);

            return Redirect();
        }
    }
}
